<template>
  <div class="z-calendar-month">
    <div class="z-calendar-month__header">
      <div v-for="day in weekDays" :key="day" class="item">{{ day }}</div>
    </div>
    <div class="z-calendar-month__body">
      <div v-for="(row, index) in rows" :key="index" class="z-calendar-month__cell" :class="row.type">
        <div class="z-calendar-month__data">
          <div class="day">{{ row.days }}</div>
          <el-link v-if="row.count > 0" type="primary" :underline="false" @click="pickFormateDate(row)">
            共{{ row.count }}节课
            <i class="el-icon-arrow-right" />
          </el-link>
        </div>
        <div v-for="item in row.list.slice(0, 1)" :key="item.sec_id" class="z-calendar-month__crad">
          <div class="time">{{ item.start_time | parseTime('{h}:{i}') }}-{{ item.end_time | parseTime('{h}:{i}') }}</div>
          <div class="title">{{ item.course_title }}</div>
        </div>
      </div>
    </div>

    <el-drawer title="课表详情" :visible.sync="drawer" :size="450">
      <div class="z-calendar-drawer__header">
        <div class="date">{{ details.timestamp | parseTime('{y}年{m}月{d}日') }}</div>
        <div class="num">共{{ details.count }}节课</div>
      </div>
      <div class="z-calendar-drawer__body">
        <div
          v-for="(item, index) in details.list"
          :key="index"
          class="z-calendar-drawer__crad"
          :class="[{ start: item.live_status == 999, end: item.live_status == 992 }]"
        >
          <div class="time">{{ item.start_time | parseTime('{h}:{i}') }}-{{ item.end_time | parseTime('{h}:{i}') }}</div>
          <div class="title">{{ item.course_title }}</div>
          <div class="salutation">{{ item.sec_title }}</div>
          <div class="name">{{ item.teacher_name }}</div>
          <div v-if="item.live_status == 999 || item.live_status == 992" class="status">{{ item.live_status == 992 ? '已结束' : '直播中' }}</div>
        </div>
      </div>
    </el-drawer>
  </div>
</template>

<script>
import { parseTime } from '@/common/js/filters.js';
import { mapState, mapGetters } from 'vuex';
import { range, getLastDayOfMonth, getFirstDayOfMonth, getPrevMonthLastDays, getMonthDays } from './date-util';

const validTypes = ['prev', 'today', 'next'];
const getWeekDaysData = (arr1, arr2) => {
  return arr1.reduce((pre, cur) => {
    const target = pre.find(e => e.date === cur.date);
    if (target) {
      Object.assign(target, cur);
    } else {
      pre.push(cur);
    }
    return pre;
  }, arr2);
};
export default {
  props: {
      value: {
        type: [Date, String, Number],
        default: _ => {
          return '';
        }
      },
      title: {
        type: String,
        default: _ => {
          return '';
        }
      },
      teacher: {
        type: String,
        default: _ => {
          return '';
        }
      }
  },
  data() {
    return {
      now: new Date(),
      list: [],
      drawer: false,
      details: {
        count: 0,
        list: [],
        timestamp: ''
      }
    };
  },
  computed: {
    ...mapState({
      userInfo: state => state.user.info,
      token: state => state.user.token
    }),
    ...mapGetters({
      globThemeColor: 'projectSetting/getGlobThemeColor'
    }),
    prevMonthDatePrefix() {
      const temp = new Date(this.date.getTime());
      temp.setDate(0);
      return parseTime(temp, '{y}-{m}');
    },
    curMonthDatePrefix() {
      return parseTime(this.date, '{y}-{m}');
    },
    nextMonthDatePrefix() {
      const temp = new Date(this.date.getFullYear(), this.date.getMonth() + 1, 1);
      return parseTime(temp, '{y}-{m}');
    },
    formatedDate() {
      return parseTime(this.date, '{y}-{m}-{d}');
    },
    formatedToday() {
      return parseTime(this.now, '{y}-{m}-{d}');
    },
    realSelectedDay: {
      get() {
        return this.formatedDate;
      },
      set(val) {
        const date = new Date(val);
        this.$emit('input', date);
      }
    },
    date() {
      return this.toDate(this.value);
    },
    rows() {
      let days = [];
      const date = this.date;
      let firstDay = getFirstDayOfMonth(date);
      firstDay = firstDay === 0 ? 7 : firstDay;
      const firstDayOfWeek = 7;
      const offset = (7 + firstDay - firstDayOfWeek) % 7;
      const prevMonthDays = getPrevMonthLastDays(date, offset).map(day => ({
        days: day,
        type: 'prev',
        date: this.getFormateDate(day, 'prev'),
        count: 0,
        list: []
      }));
      const currentMonthDays = getMonthDays(date).map(day => ({
        days: day,
        type: 'current',
        date: this.getFormateDate(day, 'current'),
        count: 0,
        list: []
      }));
      days = [...prevMonthDays, ...currentMonthDays];
      let lastDay = getLastDayOfMonth(date);
      lastDay = 7 - lastDay - 1;
      const nextMonthDays = range(lastDay).map((_, index) => ({
        days: index + 1,
        type: 'next',
        date: this.getFormateDate(index + 1, 'next'),
        count: 0,
        list: []
      }));
      days = days.concat(nextMonthDays);
      days = getWeekDaysData(this.list, days);
      return days;
    },
    weekDays() {
      return ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
    }
  },
  mounted() {
    this.getData(this.curMonthDatePrefix);
  },
  methods: {
    getData(date) {
      this.list = [];
      this.$http.get(
        '/course/admin/schedule/period',
        { startdate: this.getStartDateOfWeek(date), enddate: this.getEndDateOfWeek(date), title: this.title, teacher: this.teacher },
        res => {
          this.list = res.data.datas;
          this.list.map(item => (item.date = parseTime(item.timestamp, '{y}-{m}-{d}')));
          const sum = this.list.reduce((pre, cur) => {
            return pre + cur.count;
          }, 0);
          // this.list.map(item => (item.date = parseTime(item.start_time, '{y}-{m}-{d} {h}')));
          this.$emit('number', sum);
        }
      );
    },
    pickDay(day) {
      this.realSelectedDay = day;
      this.getData(day);
    },
    selectDate(type) {
      if (validTypes.indexOf(type) === -1) {
        throw new Error(`invalid type ${type}`);
      }
      let day = '';
      if (type === 'prev') {
        day = `${this.prevMonthDatePrefix}`;
      } else if (type === 'next') {
        day = `${this.nextMonthDatePrefix}`;
      } else {
        day = this.formatedToday;
      }
      if (day === this.formatedDate) return;
      this.pickDay(day);
    },
    toDate(val) {
      if (!val) {
        throw new Error('invalid val');
      }
      return val instanceof Date ? val : new Date(val);
    },
    getFormateDate(day, type) {
      if (!day || ['prev', 'current', 'next'].indexOf(type) === -1) {
        throw new Error('invalid day or type');
      }
      let prefix = this.curMonthDatePrefix;
      if (type === 'prev') {
        prefix = this.prevMonthDatePrefix;
      } else if (type === 'next') {
        prefix = this.nextMonthDatePrefix;
      }
      day = `00${day}`.slice(-2);
      return `${prefix}-${day}`;
    },
    pickFormateDate(data) {
      this.details = data;
      this.drawer = true;
    },
    onSearch() {
      this.getData(this.curMonthDatePrefix);
    },
    /**
     * 获取开始日期
     * @param {string} value Date string
     * @returns {string} 时间戳
     */
    getStartDateOfWeek(value) {
      const date = this.toDate(value);
      const firstDay = getFirstDayOfMonth(date);
      const offset = 7 - firstDay - 7 + 1;
      if (offset > 0) {
        date.setDate(1);
      } else {
        date.setDate(offset);
      }
      date.setHours(0, 0, 0, 0);
      return parseTime(date, '{y}-{m}-{d}');
    },
    /**
     * 获取结束日期
     * @param {string} value Date string
     * @returns {string} 时间戳
     */
    getEndDateOfWeek(value) {
      const date = this.toDate(value);
      const temp = new Date(date.getFullYear(), date.getMonth() + 1, 0);
      let lastDay = getLastDayOfMonth(temp);
      lastDay = 7 - lastDay - 1;
      if (lastDay > 0) {
        const time = new Date(date.getFullYear(), date.getMonth() + 1, lastDay);
        return parseTime(time, '{y}-{m}-{d}');
      }
      return parseTime(temp, '{y}-{m}-{d}');
    }
  }
};
</script>

<style lang="scss" scoped>
$text-color-import: #5191ff;
$text-color-auxiliary: #909399;
::v-deep .el-calendar {
  .el-calendar__body {
    padding: 0 0 35px;
  }
  .el-calendar__header,
  .el-calendar-table thead {
    display: none;
  }
  .el-calendar-table td.is-selected {
    background-color: #ffffff;
  }
  .el-calendar-table .el-calendar-day {
    padding: 0;
    height: 120px;
  }
  .el-calendar-table td.is-today {
    color: $text-color-import;
  }
  .el-calendar-table td.next,
  .el-calendar-table td.prev {
    color: $text-color-auxiliary;
  }
}
.z-calendar-month__header {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  .item {
    height: 60px;
    font-size: 14px;
    font-weight: 500;
    color: #303133;
    line-height: 60px;
    text-align: center;
    background: #f6f7fb;
    border: 1px solid #ebeef5;
    border-left: 0;
  }
  .item:nth-child(1) {
    border-left: 1px solid #ebeef5;
  }
}
.z-calendar-month__body {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  .z-calendar-month__cell {
    height: 89px;
    padding: 20px 10px 12px;
    line-height: 1;
    border-bottom: 1px solid #ebeef5;
    border-left: 1px solid #ebeef5;
  }
  .z-calendar-month__cell:nth-child(7n) {
    border-right: 1px solid #ebeef5;
  }
  .z-calendar-month__data {
    display: flex;
    align-items: center;
    justify-content: space-between;
    .day {
      font-size: 16px;
      font-weight: 500;
      color: $text-color-import;
    }
    .el-link {
      font-size: 12px;
    }
  }
  .z-calendar-month__crad {
    margin-top: 17px;
    padding: 10px 9px;
    background: #f6f7fb;
    border-radius: 4px;
    .time {
      font-size: 12px;
      font-weight: 400;
      color: $text-color-import;
    }
    .title {
      margin-top: 10px;
      font-size: 13px;
      font-weight: 400;
      color: $text-color-import;
      max-width: 85px;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
  }
  .prev .z-calendar-month__data .day,
  .next .z-calendar-month__data .day {
    color: $text-color-auxiliary;
  }
}

.z-calendar-drawer__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
  .date {
    font-size: 15px;
    font-weight: 500;
    color: $text-color-import;
  }
  .num {
    font-size: 14px;
    font-weight: 400;
    color: $text-color-auxiliary;
  }
}
.z-calendar-drawer__body {
  // width: 390px;
  padding: 0 20px;
  .z-calendar-drawer__crad {
    padding: 20px 10px;
    background: #f6f7fb;
    border-radius: 4px;
    line-height: 1;
    position: relative;
    cursor: pointer;
    transition: all 0.2s;
    box-sizing: border-box;
    margin-top: 20px;
    .time {
      font-size: 14px;
      font-weight: 400;
      color: $text-color-import;
    }
    .title {
      max-width: 330px;
      margin-top: 15px;
      font-size: 14px;
      font-weight: 500;
      color: $text-color-import;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .salutation {
      max-width: 330px;
      margin-top: 5px;
      font-size: 12px;
      font-weight: 400;
      color: $text-color-auxiliary;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .name {
      max-width: 330px;
      margin-top: 15px;
      font-size: 12px;
      font-weight: 400;
      color: $text-color-auxiliary;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .status {
      position: absolute;
      right: 0;
      top: 0;
      padding: 3px 2px;
      font-size: 12px;
      font-weight: 400;
      color: #ffffff;
      border-radius: 0px 4px 0px 4px;
    }
    &.start {
      .status {
         background: #5191FF;
      }
    }
    &.end {
      .time,
      .title {
        color: $text-color-auxiliary;
      }
      .status {
        background: #b7bac1;
      }
    }
    &:hover {
      background: #f0f1f6;
    }
  }
}
</style>
